home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Forward task -- Handle messages whose path is to LEAVE, DONE, or ? *)
- (* *)
- (* Copyright 1990, 1991 by H. Roy Engehausen. All rights reserved. *)
- (* *)
- (*===========================================================================*)
-
- {$UNDEF DEBUG_LEAVE}
-
- PROCEDURE do_leave;
-
- VAR
- age_pos : BYTE;
- done_sw : BOOLEAN;
- i : BYTE;
- j : WORD;
- last_route : msg_r_ptr;
- leave_sw : BOOLEAN;
- msg_age : LONGINT;
- next_route : msg_r_ptr;
- qmark_sw : BOOLEAN;
- route_kill_sw : BOOLEAN;
- this_dr : msg_dr_ptr;
- this_flag : msg_flag_type;
- this_inx : BYTE;
- this_msg : msg_index_ptr;
- this_route : msg_r_ptr;
-
- LABEL
- go_next_msg,
- leave_loop;
-
- (*=========================================================================*)
- (* Subprocedure to set the minimum age of a message. *)
- (*=========================================================================*)
-
- PROCEDURE set_msg_age;
-
- VAR
- code : INTEGER;
- hours : INTEGER;
- hour_sum : WORD;
- word_max : INTEGER;
- word_no : BYTE;
- word_to_do : STRING[4];
-
- LABEL
- iterate;
-
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* Initialize counters *)
- (*---------------------------------------------------------------------*)
-
- msg_age := max_time;
-
- hour_sum := 0;
-
- (*---------------------------------------------------------------------*)
- (* Get the number of words to test. If none, we are done *)
- (*---------------------------------------------------------------------*)
-
- word_max := age_pos - 1;
- IF word_max < 1 THEN EXIT;
-
- (*---------------------------------------------------------------------*)
- (* Loop thru the words *)
- (*---------------------------------------------------------------------*)
-
- word_no := word_max;
- WHILE word_no > 0 DO
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* Get the word to be evaulated and see if it is short enough *)
- (*-----------------------------------------------------------------*)
-
- word_to_do := SUBWORD(@this_route^.msg_r_info, word_no, 1);
- IF LENGTH(word_to_do) > 3 THEN
- GOTO iterate;
-
- (*-----------------------------------------------------------------*)
- (* Evaluate the word *)
- (*-----------------------------------------------------------------*)
-
- VAL(word_to_do, hours, code);
-
- (*-----------------------------------------------------------------*)
- (* Reject certain things *)
- (*-----------------------------------------------------------------*)
-
- IF code <> 0 THEN GOTO iterate;
- IF hours < 0 THEN GOTO iterate;
-
- (*-----------------------------------------------------------------*)
- (* The data is valid *)
- (*-----------------------------------------------------------------*)
-
- hour_sum := hour_sum + hours;
-
- (*-----------------------------------------------------------------*)
- (* If there is no plus sign then data is absolute. Compute *)
- (* minimum path age and we are done *)
- (*-----------------------------------------------------------------*)
-
- IF word_to_do[1] <> '+' THEN
- BEGIN;
- msg_age := current_day_time - LONGINT(hours) * ticks_per_hour;
- EXIT;
- END;
-
- (*----------------------------------------------------------------*)
- (* Loop end for loop thru each word *)
- (*-----------------------------------------------------------------*)
-
- iterate:
-
- DEC(word_no);
-
- END; (*----- End of loop thru words ---------------------------------*)
-
- (*---------------------------------------------------------------------*)
- (* Compute the maximum path age and we are done *)
- (*---------------------------------------------------------------------*)
-
- msg_age := current_day_time - LONGINT(hour_sum) * ticks_per_hour;
-
- END;
-
- (*=========================================================================*)
- (* Main line *)
- (*=========================================================================*)
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* Initialize *)
- (*-----------------------------------------------------------------------*)
-
- last_route := NIL;
- this_route := msg_route_list;
-
- (*-----------------------------------------------------------------------*)
- (* Look down all the routes *)
- (*-----------------------------------------------------------------------*)
-
- WHILE this_route <> NIL DO
- BEGIN;
-
- {$IFDEF POINT_CHK}
- test_pointer(this_route);
- {$ENDIF}
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Process leave = ', this_route^.msg_r_info);
- DELAY(2000);
- {$ENDIF}
-
- (*-------------------------------------------------------------------*)
- (* Point to next route *)
- (*-------------------------------------------------------------------*)
-
- next_route := this_route^.msg_r_next;
-
- (*-------------------------------------------------------------------*)
- (* See if we need action *)
- (*-------------------------------------------------------------------*)
-
- i := 0;
-
- age_pos := FIND(@this_route^.msg_r_info, @done);
- IF age_pos <> 0 THEN
- BEGIN;
- done_sw := TRUE;
- INC(i);
- END
- ELSE
- done_sw := FALSE;
-
- j := FIND(@this_route^.msg_r_info, @qmark);
- IF j <> 0 THEN
- BEGIN;
- qmark_sw := TRUE;
- age_pos := j;
- INC(i);
- END
- ELSE
- qmark_sw := FALSE;
-
- leave_sw := FIND(@this_route^.msg_r_info, @leave) <> 0;
- IF leave_sw THEN
- INC(i);
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Leave actions = ', done_sw, ' ',
- qmark_sw, ' ',
- leave_sw, ' ');
- DELAY(2000);
- {$ENDIF}
-
- (*-------------------------------------------------------------------*)
- (* Look for errors *)
- (*-------------------------------------------------------------------*)
-
- IF i > 1 THEN
- BEGIN;
- window_write(prefix_str, 'Route line has multiple ?, DONE, LEAVE');
- window_write(prefix_str, this_route^.msg_r_info);
- END;
-
- (*-------------------------------------------------------------------*)
- (* Now take appropriate action *)
- (*-------------------------------------------------------------------*)
-
- IF NOT (qmark_sw OR done_sw OR leave_sw) THEN
-
- (*-----------------------------------------------------------------*)
- (* This route has none of the actions. Just forward the chaining *)
- (*-----------------------------------------------------------------*)
-
- last_route := this_route
- ELSE
-
- (*-----------------------------------------------------------------*)
- (* Handle the action needed *)
- (*-----------------------------------------------------------------*)
-
- BEGIN;
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Leave process = ', this_route^.msg_r_info);
- DELAY(2000);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Compute message age *)
- (*---------------------------------------------------------------*)
-
- set_msg_age;
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Action time = ', current_day_time - msg_age);
- DELAY(2000);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Assume we throw away the route when done *)
- (*---------------------------------------------------------------*)
-
- route_kill_sw := TRUE;
-
- (*---------------------------------------------------------------*)
- (* Loop while we adjust the messages *)
- (*---------------------------------------------------------------*)
-
- this_msg := NIL;
-
- WHILE TRUE DO
- BEGIN;
-
- go_next_msg:
-
- (*-----------------------------------------------------------*)
- (* Find a message that this points to. If we can't we are *)
- (* done *)
- (*-----------------------------------------------------------*)
-
- this_msg := find_next_msg(this_route, this_msg, this_inx);
-
- IF this_msg = NIL THEN
- GOTO leave_loop;
-
- {$IFDEF POINT_CHK}
- test_pointer(this_msg);
- {$ENDIF}
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Leave message = ', this_msg^.msg_i_mb.msg_number,
- '/', this_inx);
- DELAY(2000);
- {$ENDIF}
-
- (*-----------------------------------------------------------*)
- (* If we are checking for done then check the message age *)
- (* too. If not old enough, skip the message and the route *)
- (* is still good *)
- (*-----------------------------------------------------------*)
-
- IF this_msg^.msg_i_mb.msg_dt_in > msg_age THEN
- BEGIN;
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Age bypass');
- DELAY(2000);
- {$ENDIF}
-
- route_kill_sw := FALSE;
- GOTO go_next_msg;
-
- END;
-
- (*-----------------------------------------------------------*)
- (* Get the flag into a handy place *)
- (*-----------------------------------------------------------*)
-
- this_flag := this_msg^.msg_i_mb.msg_flag;
-
- (*-----------------------------------------------------------*)
- (* If we are routing to "?" then set the flag *)
- (*-----------------------------------------------------------*)
-
- IF qmark_sw THEN
- this_flag := this_flag OR mf_unknown;
-
- (*-----------------------------------------------------------*)
- (* Check for regular message or distribution list *)
- (*-----------------------------------------------------------*)
-
- IF this_inx = 0 THEN
- BEGIN;
-
- (*-------------------------------------------------------*)
- (* Regular message. Reset the route pointer and flag *)
- (*-------------------------------------------------------*)
-
- this_msg^.msg_i_rou := NIL;
- this_flag := this_flag
- AND NOT (mf_fwd_select OR mf_fwd_process);
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Reset main flag');
- DELAY(2000);
- {$ENDIF}
-
- (*-------------------------------------------------------*)
- (* If DONE then say so *)
- (*-------------------------------------------------------*)
-
- IF done_sw THEN
- BEGIN;
- this_flag := this_flag OR mf_fwd;
- IF POS(this_msg^.msg_i_mb.msg_type,
- opt_block.nofwd_kill) = 0 THEN
- this_flag := this_flag OR mf_kill
- END;
-
- END
- ELSE
-
- (*---------------------------------------------------------*)
- (* Distribution list. We will only process things *)
- (* if the distribution route list is also present. *)
- (* It should be impossible to get here if it ain't *)
- (*---------------------------------------------------------*)
-
- IF (this_flag AND mf_disrout) <> 0 THEN
- BEGIN;
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Reset dist flag');
- DELAY(2000);
- {$ENDIF}
-
- (*-----------------------------------------------------*)
- (* Get pointer to distribution route block *)
- (*-----------------------------------------------------*)
-
- this_dr := this_msg^.msg_i_dr;
-
- {$IFDEF POINT_CHK}
- test_pointer(this_dr);
- {$ENDIF}
-
- (*-----------------------------------------------------*)
- (* Now get pointer to distribution block *)
- (*-----------------------------------------------------*)
-
- {$IFDEF POINT_CHK}
- test_pointer(this_dr^.msg_dr_dblk);
- {$ENDIF}
-
- (*-----------------------------------------------------*)
- (* Change the flags for this item *)
- (*-----------------------------------------------------*)
-
- WITH this_dr^.msg_dr_dblk^.msg_d_array[this_inx] DO
- BEGIN;
-
- (*-------------------------------------------------*)
- (* Reset the forward flags *)
- (*-------------------------------------------------*)
-
- msg_d_flag := msg_d_flag AND
- ($FF - (df_fwd_select OR df_fwd_process));
-
- (*-------------------------------------------------*)
- (* Turn on "?" if needed *)
- (*-------------------------------------------------*)
-
- IF qmark_sw THEN
- msg_d_flag := msg_d_flag OR df_fwd_unknown;
-
- (*-------------------------------------------------*)
- (* Turn on "DONE" if needed *)
- (*-------------------------------------------------*)
-
- IF done_sw THEN
- msg_d_flag := msg_d_flag OR df_fwd;
-
- END;
-
- (*-----------------------------------------------------*)
- (* See if we still are going to send this message out *)
- (*-----------------------------------------------------*)
-
- i := 1;
- j := this_dr^.msg_dr_dblk^.msg_d_no;
- WHILE (i <= j) AND (this_dr^.msg_dr_data[i] = NIL) DO
- INC(i);
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Dist block clean -- ', i ,'/', j);
- DELAY(2000);
- {$ENDIF}
-
- (*-----------------------------------------------------*)
- (* If we aren't, then we can free things *)
- (*-----------------------------------------------------*)
-
- IF i > j THEN
- BEGIN;
-
- (*-------------------------------------------------*)
- (* Unchain the distribution route block *)
- (*-------------------------------------------------*)
-
- this_msg^.msg_i_dis := this_dr^.msg_dr_dblk;
-
- (*-------------------------------------------------*)
- (* Calculate size of the block and free it *)
- (*-------------------------------------------------*)
-
- j := j * SIZEOF(msg_dr_route_item)
- + SIZEOF(msg_d_ptr);
- FREEMEM(this_dr, j);
-
- {$IFDEF DEBUG_LEAVE}
- WRITELN('Dist block free -- ', j);
- DELAY(2000);
- {$ENDIF}
-
- {$IFDEF FREE_CHK}
- test_free_list;
- {$ENDIF}
-
- (*-------------------------------------------------*)
- (* Turn off appropriate flags *)
- (*-------------------------------------------------*)
-
- this_flag := this_flag
- AND NOT (mf_disrout
- OR mf_fwd_select
- OR mf_fwd_process);
-
- END; (*----- End handling distribution list cleanup -*)
-
- END; (*----- End handling distribution list -------------*)
-
- (*-----------------------------------------------------------*)
- (* Put the flag back *)
- (*-----------------------------------------------------------*)
-
- this_msg^.msg_i_mb.msg_flag := this_flag;
-
- (*-----------------------------------------------------------*)
- (* If we did a permanent change then make it permanent *)
- (*-----------------------------------------------------------*)
-
- IF done_sw THEN
- BEGIN;
- update_msg(this_msg);
- IF (this_flag AND mf_kill) <> 0 THEN
- log_data_is(this_msg^.msg_i_mb.msg_number, 'FK DONE')
- ELSE
- log_data_is(this_msg^.msg_i_mb.msg_number, 'F DONE');
- END;
-
- END; (*----- End loop thru all the messages for this route ----*)
-
- leave_loop:
-
- (*---------------------------------------------------------------*)
- (* See if we are done with this route block *)
- (*---------------------------------------------------------------*)
-
- IF route_kill_sw THEN
- BEGIN;
-
- (*-----------------------------------------------------------*)
- (* Unchain it from the list *)
- (*-----------------------------------------------------------*)
-
- IF last_route <> NIL THEN
- last_route^.msg_r_next := next_route
- ELSE
- msg_route_list := next_route;
-
- (*-----------------------------------------------------------*)
- (* Destroy this route block *)
- (*-----------------------------------------------------------*)
-
- DISPOSE(this_route);
-
- {$IFDEF FREE_CHK}
- test_free_list;
- {$ENDIF}
-
- END;
-
- END; (*----- End handling LEAVE, DONE, and "?" -------------------*)
-
- (*-------------------------------------------------------------------*)
- (* Chain to next route *)
- (*-------------------------------------------------------------------*)
-
- this_route := next_route;
-
- END; (*----- end loop thru all the routes -----------------------------*)
-
- END;